/*
 * Copyright (C) 2007-2012 Geometer Plus <contact@geometerplus.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 */

package org.geometerplus.fbreader.fbreader;

import android.graphics.Rect;

import org.geometerplus.zlibrary.core.filesystem.ZLFile;
import org.geometerplus.zlibrary.core.xml.ZLStringMap;
import org.geometerplus.zlibrary.core.xml.ZLXMLReaderAdapter;

import java.io.IOException;
import java.util.HashMap;

public class TapZoneMap {
    public enum Tap {
        singleTap,
		singleNotDoubleTap,
		doubleTap
    }

    private int myVerticalSize = 3;
    private int myHorizontalSize = 3;
	private final HashMap<Zone,String> myZoneMap = new HashMap<Zone,String>();
	private final HashMap<Zone,String> myZoneMap2 = new HashMap<Zone,String>();
   
	private final HashMap<RectangleZone,String> myRectangleZoneMap = new HashMap<RectangleZone,String>();
		
	TapZoneMap(int v, int h) {
		myVerticalSize = v;
		myHorizontalSize = h;
		FBReaderApp reader = (FBReaderApp) FBReaderApp.Instance();
		ZLAndroidWidget widet = (ZLAndroidWidget) reader.getViewWidget();
		
//		RectangleZone rectangleZone = 
//				new RectangleZone((int)(widet.getWidth() * 0.4), (int)(widet.getHeight() * 0.4),(int)( widet.getWidth() * 0.2),(int)( widet.getHeight() * 0.2));
//		addRectangleTapZone(rectangleZone, ActionCode.SHOW_OR_HIDE_READ_MENU);
	}

	TapZoneMap(String name) {
		final ZLFile mapFile = ZLFile.createFileByPath(
                "read_engine/default/tapzones/" + name.toLowerCase() + ".xml"
        );
        try {
            new Reader().read(mapFile);
        } catch (IOException e) {
            e.printStackTrace();
        }
        FBReaderApp reader = (FBReaderApp) FBReaderApp.Instance();
		ZLAndroidWidget widet = (ZLAndroidWidget) reader.getViewWidget();
		
//		RectangleZone rectangleZone = 
//				new RectangleZone((int)(widet.getWidth() * 0.4), (int)(widet.getHeight() * 0.4),(int)( widet.getWidth() * 0.2),(int)( widet.getHeight() * 0.2));
//		addRectangleTapZone(rectangleZone, ActionCode.SHOW_OR_HIDE_READ_MENU);
	}

	public Object getActionExtralDataByCoordinates(int x, int y, int width, int height, Tap tap)
	{
		if (width == 0 || height == 0) {
			return null;
		}
		for(RectangleZone rectZone: myRectangleZoneMap.keySet())
		{
			if(rectZone.contains(x, y))
			{
				return rectZone.getExtralData();
			}
		}
		
		return null;
	}

	public String getActionByCoordinates(int x, int y, int width, int height, Tap tap){
		return getActionByCoordinates(x,y,width,height,tap,y);

	}

	public String getActionByCoordinates(int x, int y, int width, int height, Tap tap,int tempY) {
		if (width == 0 || height == 0) {
			return null;
		}

		if(tempY == -1){
			tempY = y;
		}

		for(RectangleZone rectZone: myRectangleZoneMap.keySet())
		{
			if(rectZone.contains(x, tempY))
			{
				return myRectangleZoneMap.get(rectZone);
			}
		}
		
		final Zone zone = new Zone(myHorizontalSize * x / width, myVerticalSize * y / height);
		switch (tap) {
			case singleTap:
			{
				final String action = myZoneMap.get(zone);
				return action != null ? action : myZoneMap2.get(zone);
			}
			case singleNotDoubleTap:
				return myZoneMap.get(zone);
			case doubleTap:
				return myZoneMap2.get(zone);
		}
		return null;
	}

	public static class RectangleZone extends Zone
	{
		private Rect touchZone;


		RectangleZone(int x, int y, int w, int h) {
			super(0, 0);
			touchZone = new Rect(x, y, x + w, y + h);
			
		}

		public void setRect(int x, int y, int w, int h){
			touchZone.set(x, y, x + w, y + h);
		}

		RectangleZone(){
			super(0,0);
			touchZone = new Rect();
		}
		public boolean contains(int x, int y)
		{
			return touchZone.contains(x, y);
		}
		public final Rect getTouchZone(){
			return touchZone;
		}
		@Override
		public boolean equals(Object o) {
			if (o == this) {
				return true;
			}

			if (!(o instanceof RectangleZone)) {
				return false;
			}
			RectangleZone rz = (RectangleZone)o;
			return touchZone.equals(rz.touchZone);
		}


	}
	private static class Zone {
		int HIndex;
		int VIndex;

		Zone(){

		}
		Zone(int h, int v) {
			HIndex = h;
			VIndex = v;
		}

		/*void mirror45() {
			final int swap = HIndex;
			HIndex = VIndex;
			VIndex = swap;
		}*/

		@Override
		public boolean equals(Object o) {
			if (o == this) {
				return true;
			}

			if (!(o instanceof Zone)) {
				return false;
			}

			final Zone tz = (Zone)o;
			return HIndex == tz.HIndex && VIndex == tz.VIndex;
		}

		@Override
		public int hashCode() {
			return (HIndex << 5) + VIndex;
		}
		
		private Object eventExtralData = null;
		public void setExtralData(Object obj)
		{
			eventExtralData = obj;
		}
		public Object getExtralData()
		{
			return eventExtralData;
		}
	}

	private class Reader extends ZLXMLReaderAdapter {
		@Override
		public boolean startElementHandler(String tag, ZLStringMap attributes) {
			try {
				if ("zone".equals(tag)) {
					final int x = Integer.parseInt(attributes.getValue("x"));
					final int y = Integer.parseInt(attributes.getValue("y"));
					final String action = attributes.getValue("action");
					final String action2 = attributes.getValue("action2");
					if (action != null) {
						myZoneMap.put(new Zone(x, y), action);
					}
					if (action2 != null) {
						myZoneMap2.put(new Zone(x, y), action2);
					}
				} else if ("tapZones".equals(tag)) {
					final String v = attributes.getValue("v");
					if (v != null) {
						myVerticalSize = Integer.parseInt(v);
					}
					final String h = attributes.getValue("h");
					if (h != null) {
						myHorizontalSize = Integer.parseInt(h);
					}
				}
			} catch (Throwable e) {
			}
			return false;
		}
		
	}
	
	public synchronized boolean addRectangleTapZone(RectangleZone key, String actionName)
	{
		if(key == null)
		{
			return false;
		}
		if(myRectangleZoneMap.containsKey(key))
		{
			myRectangleZoneMap.remove(key);
		}

		myRectangleZoneMap.put(key, actionName);
		
		return true;
	}
	public synchronized boolean removeRectangleTapZoneByName(RectangleZone key)
	{
		
		if(myRectangleZoneMap.containsKey(key))
		{
			myRectangleZoneMap.remove(key);
		}


		return true;
	}

	public void clear(){
		myRectangleZoneMap.clear();
	}

}
